package com.futuristik.arkitek;

import java.io.OutputStream;
import java.util.ArrayList;
import java.util.List;

import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.files.FileHandle;
import com.badlogic.gdx.graphics.Texture;
import com.badlogic.gdx.graphics.Texture.TextureWrap;
import com.badlogic.gdx.physics.box2d.World;
import com.badlogic.gdx.utils.Json;
import com.futuristik.objects.ArkitekObject;
import com.futuristik.objects.BrickFloor;
import com.futuristik.objects.Edge;
import com.futuristik.objects.Flag;
import com.futuristik.objects.IceFloor;
import com.futuristik.objects.Spikes;
import com.futuristik.objects.Spring;
import com.futuristik.objects.StickyFloor;

public class Map {
	public String name;
	public String fileName;
	public Texture backgroundTexture;
	public ArrayList<ArkitekObject> objects = new ArrayList<ArkitekObject>();
	public ArrayList<Edge> worldEdges = new ArrayList<Edge>();
	public int width;
	public int height;

	public Map () {
		//Initialize Level Here (load level etc)
		backgroundTexture = new Texture(Gdx.files.internal("data/bg.jpg"));
		backgroundTexture.setWrap(TextureWrap.Repeat, TextureWrap.Repeat);
        backgroundTexture.setFilter(Texture.TextureFilter.Linear, Texture.TextureFilter.Linear);
		
        width = 80;
        height = 40;
	}
	
	public Map (String fileName, boolean ext){
		this();
		if(ext)
			loadMap(fileName);
		else
			loadChallenge(fileName);
	}
	
	public Map (String fileName){
		this(fileName, true);
	}

	public void setupWorld(World w){
        Edge.generateWorldEdges(worldEdges, width, height);
		
		for(int i = 0; i < worldEdges.size(); i++){
			worldEdges.get(i).create(w);
		}
		
		for(ArkitekObject obj : objects){
			obj.create(w);
		}
	}
	
	public String toJSON(){
		ArrayList<String> ret = new ArrayList<String>();
		if(name == null){
			name = "My Map";
		}
		ret.add("mapName "+name);
		for(ArkitekObject v : objects){
			ret.add(v.toString());
		}
		Json j = new Json();	
		return j.toJson(ret);
	}
	
	public void save(){
		this.save(fileName);
	}
	
	public void save(String filename){
		FileHandle handle = Gdx.files.external("arkitekMaps/"+filename+".txt");
		
		Gdx.files.external("arkitekMaps/").mkdirs();
		OutputStream output = handle.write(false);
		try{
			output.write(this.toJSON().getBytes());
			output.close();
		} catch(Exception e){}			
	}
	
	public boolean loadMap(String filename){
		FileHandle handle = Gdx.files.external("arkitekMaps/"+filename);
		
		fileName = handle.nameWithoutExtension();
		
		if(handle.extension().equals("txt"))
			return this.load(handle.readString());
		else
			return false;
	}
	
	public boolean loadChallenge(String filename){
		FileHandle handle = Gdx.files.internal("data/maps/"+filename);
		
		if(handle.extension().equals("txt"))
			return this.load(handle.readString());
		else
			return false;
	}
	
	public String getMapName(String filename){
		Json j = new Json();
		ArrayList<String> lst = j.fromJson(ArrayList.class, Gdx.files.external("arkitekMaps/"+filename).readString());		
		return lst.get(0).substring(8);
	}
	
	public int getWidth() {
		return width;
	}
	
	public int getHeight() {
		return height;
	}
	
	public boolean load(String str){
		Json j = new Json();
		ArrayList<String> lst = j.fromJson(ArrayList.class, str);
		for(String s : lst){
			String[] exp = s.split(" ");
			String className = exp[0];
			
			int n = exp.length - 1;
			
			if(className.equals("BrickFloor")){
				if(n == 4)
					objects.add(new BrickFloor(Float.parseFloat(exp[1]), Float.parseFloat(exp[2]), Float.parseFloat(exp[3]), Float.parseFloat(exp[4])));
				else
					return false;
			}
			else if(className.equals("IceFloor")){
				if(n == 4)
					objects.add(new IceFloor(Float.parseFloat(exp[1]), Float.parseFloat(exp[2]), Float.parseFloat(exp[3]), Float.parseFloat(exp[4])));
				else
					return false;
			}
			else if(className.equals("StickyFloor")){
				if(n == 4)
					objects.add(new StickyFloor(Float.parseFloat(exp[1]), Float.parseFloat(exp[2]), Float.parseFloat(exp[3]), Float.parseFloat(exp[4])));
				else
					return false;
			}
			else if(className.equals("Spring")){
				if(n == 3)
					objects.add(new Spring(Float.parseFloat(exp[1]), Float.parseFloat(exp[2]), Float.parseFloat(exp[3])));
				else
					return false;
			}
			else if(className.equals("Spikes")){
				if(n == 3)
					objects.add(new Spikes(Float.parseFloat(exp[1]), Float.parseFloat(exp[2]), Float.parseFloat(exp[3])));
				else
					return false;
			}
			else if(className.equals("Flag")){
				if(n == 3)
					objects.add(new Flag(Float.parseFloat(exp[1]), Float.parseFloat(exp[2]), Float.parseFloat(exp[3])));
				else
					return false;
			}
			else if(className.equals("bg")){
				backgroundTexture = new Texture(Gdx.files.internal("data/maps/"+s.substring(3)));
				backgroundTexture.setWrap(TextureWrap.Repeat, TextureWrap.Repeat);
		        backgroundTexture.setFilter(Texture.TextureFilter.Linear, Texture.TextureFilter.Linear);
			}
			else if(className.equals("mapName")){
				name = s.substring(8);
			}
			else{
				//Uh oh
				return false;
			}			
		}
		return true;
	}
	
	public List<Flag> getFlags(){
		List<Flag> lst = new ArrayList<Flag>();
		for(ArkitekObject v : objects){
			if(v.getClass().getSimpleName().equals("Flag")){
				lst.add((Flag) v);
			}
		}
		return lst;
	}

	public List<ArkitekObject> getObjects(){
		return objects;
	}
	
	public String toString(){
		return name;
	}
}



